/*
package com.thread.threadfirst.http.loan.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fugui.marvel.common.constants.CommonConstants;
import com.fugui.marvel.common.dto.Page;
import com.fugui.marvel.common.enums.*;
import com.fugui.marvel.common.utils.*;
import com.fugui.marvel.common.utils.httpclient.HttpClient;
import com.fugui.marvel.service.common.domain.loan.TCreditBank;
import com.fugui.marvel.service.common.domain.loan.TCreditCard;
import com.fugui.marvel.service.common.domain.loan.TCreditOrder;
import com.fugui.marvel.service.common.domain.user.TUser;
import com.fugui.marvel.service.common.domain.user.TUserAgential;
import com.fugui.marvel.service.common.dto.display.LeaderBoardJpaDTO;
import com.fugui.marvel.service.common.form.profitform.ProfitThreeForm;
import com.fugui.marvel.service.common.repository.loan.CreditCardRepository;
import com.fugui.marvel.service.common.repository.loan.CreditOrderRepository;
import com.fugui.marvel.service.common.repository.loan.CreditProductRepository;
import com.fugui.marvel.service.common.service.fastdfs.UploadService;
import com.fugui.marvel.service.common.service.feign.client.loan.FeignCreditServiceClient;
import com.fugui.marvel.service.common.service.feign.client.notice.FeignNoticeSendClient;
import com.fugui.marvel.service.common.service.feign.client.payment.FeignProfitTaskServiceClient;
import com.fugui.marvel.service.common.service.feign.client.redis.FeignRedisServiceClient;
import com.fugui.marvel.service.common.service.feign.client.user.FeignAgentialAccountServiceClient;
import com.fugui.marvel.service.common.service.feign.client.user.FeignUserRelationServiceClient;
import com.fugui.marvel.service.common.service.feign.client.user.FeignUserServiceClient;
import com.fugui.marvel.service.loan.pool.ThreadPool;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.persistence.criteria.*;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.Executor;

*/
/**
 * @author saving
 * @date 2019/9/18
 * @description 申卡服务
 *//*

@Service
@RestController
@Api(value = "申卡接口服务", tags = "申卡接口服务")
@RefreshScope
public class CreditServiceImpl implements FeignCreditServiceClient {

	Logger logger = LoggerFactory.getLogger(CreditServiceImpl.class);
	*/
/**
	 * 生产地址
	 *//*

	@Value(value = "${weiqiatong.baseHost}")
	private String baseHost;

	*/
/**
	 * 站点id
	 *//*

	@Value(value = "${weiqiatong.oemID}")
	private String oemID;

	*/
/**
	 * 商户号
	 *//*

	@Value(value = "${weiqiatong.merchant}")
	private String merchant;

	*/
/**
	 * 公钥
	 *//*

	@Value(value = "${weiqiatong.publicKey}")
	private String publicKey;

	*/
/**
	 * 私钥
	 *//*

	@Value(value = "${weiqiatong.privateKey}")
	private String privateKey;

	@Value(value = "${weiqiatong.callbackCreditUrl}")
	private String callbackCreditUrl;

	@Autowired
	private CreditProductRepository creditProductRepository;
	@Autowired
	private CreditCardRepository creditCardRepository;
	@Autowired
	private CreditOrderRepository creditOrderRepository;
	@Autowired
	private FeignRedisServiceClient feignRedisServiceClient;
	@Autowired
	private FeignNoticeSendClient feignNoticeSendClient;
	@Autowired
	private FeignUserServiceClient feignUserServiceClient;
	@Autowired
	private Executor executor;
	@Autowired
	private UploadService uploadService;
	@Autowired
	private FeignProfitTaskServiceClient feignProfitTaskServiceClient;
	@Autowired
	private FeignAgentialAccountServiceClient feignAgentialAccountServiceClient;
	@Autowired
	private FeignUserRelationServiceClient feignUserRelationServiceClient;


	@Value("${fastdfs.base.url}")
    private String FASTDFS_BASE_URL;
	@Value(value = "${loan.platform.profitPercent}")
	private String profitPercent;

	@Override
	@ApiOperation(value = "同步第三方银行及卡通道接口")
	@RequestMapping(method = RequestMethod.POST, value = "/m2.0/credit/getBankListFromThird")
	public void getBankListFromThird() {
		String url = baseHost + "/credit/open/apply/card/bank";
		// 生成时间戳
		String timestamp = String.valueOf(System.currentTimeMillis());
		// 公钥加密
		String sign = RsaUtils.encrypt(publicKey, String.valueOf(timestamp));
		// 建立请求头部数据
		Map<String, String> baseMap = new HashMap<>();
		baseMap.put("X-Auth-OEM", oemID);
		baseMap.put("X-Open-Sign", sign);
		baseMap.put("X-Open-Merchant", merchant);
		baseMap.put("X-Open-Timestamp", timestamp);

		logger.info("baseMap=" + baseMap.toString() +" url=" + url + " timestamp=" + timestamp + ",sign=" + sign + ",同步申卡银行解析结果=" + RsaUtils.decrypt(privateKey, sign));
		// 建立GET请求
		String resultText = HttpClient.doGet(url, baseMap);

		logger.info("信用卡同步银行通道resultText={}" + resultText);

		JSONObject object = null;
		try {
			object = JSONObject.parseObject(resultText);
		} catch (Exception e) {
			logger.error("getBankListFromThird JSONObject parseObject error");
		}
		if (object == null) {
			return;
		}
		List<String> bankIdList= new ArrayList<>();
		if (object.containsKey("status")) {
			String status = object.getString("status");
			if (CommonConstants.LEY_RESULT_SUCCESS.equals(status)) {
				JSONArray array = JSONArray.parseArray(object.getString("result"));
				for (int i = 0; i < array.size(); i++) {
					String bankId = array.getJSONObject(i).getString("id");
					String code = array.getJSONObject(i).getString("code");
					String name = array.getJSONObject(i).getString("name");
					String iconPath = array.getJSONObject(i).getString("iconPath");
					String stationChannelId = array.getJSONObject(i).getString("stationChannelId");

					String description = array.getJSONObject(i).getString("description");

					String enable = array.getJSONObject(i).getString("enable");
					String tag = array.getJSONObject(i).getString("tag");

					Integer sort = array.getJSONObject(i).getInteger("sort");

					TCreditBank bank = new TCreditBank();
					bank.setBankId(bankId);
					bank.setBankCode(code);
					bank.setBankName(name);
					bank.setIconPath(iconPath);
					bank.setStationChannelId(stationChannelId);
					Integer thirdStatus = 0;
					if ("ACTIVATE".equalsIgnoreCase(enable)) {
						thirdStatus = 1;
					}
					bank.setThridStatus(thirdStatus);
					bank.setSort(sort);
					bank.setBankTag(tag);
					bank.setDescription(description);
					bank.setStatus(ChannelStatusTypeEnum.TYPE_DOWN.getKey());

					TCreditBank tbank = creditProductRepository.queryTCreditBankByBankId(bankId);
					if (tbank != null) {
						bank.setId(tbank.getId());
						bank.setUpdateTime(new Date());
						UpdateTool.copyProperties(tbank, bank);
					} else {
						bank.setCreateTime(new Date());
					}

					bank.setMarketId(MarketTypeEnum.TYPE_WECHARTTONG.getKey());
					creditProductRepository.save(bank);
					bankIdList.add(bankId);
					ThreadPool.getThreadPool().executor(new Runnable() {
						@Override
						public void run() {
							getCardListFromThird(bankId, 1);
						}
					});
				}
			}
		} else {
			logger.error("getBankListFromThird return data execption resultText={}", resultText);
		}
		if(bankIdList != null && bankIdList.size() > 0) {
			creditProductRepository.updateTCreditBankByBankId(bankIdList);
		}
		logger.info("信用卡同步银行通道完成");

	}

	public void getCardListFromThird(String bankId, int page) {

		String url = baseHost + "/credit/open/apply/card/channel";
		// 生成时间戳
		String timestamp = String.valueOf(System.currentTimeMillis());
		// 公钥加密
		String sign = RsaUtils.encrypt(publicKey, String.valueOf(timestamp));
		// 建立请求头部数据
		Map<String, String> baseMap = new HashMap<>();
		baseMap.put("X-Auth-OEM", oemID);
		baseMap.put("X-Open-Sign", sign);
		baseMap.put("X-Open-Merchant", merchant);
		baseMap.put("X-Open-Timestamp", timestamp);

		logger.info("timestamp=" + timestamp + ",sign=" + sign + ",同步申卡银行通道解析结果=" + RsaUtils.decrypt(privateKey, sign));

		List<Long> list = new ArrayList<Long>();
		list.add(Long.valueOf(bankId));
		Map<String, Object> map = new HashMap<>();
		map.put("bankIds", list);
		map.put("current", page);

		String json = JSON.toJSONString(map);
		// 建立post请求
		String resultText = HttpClient.doPost(url, baseMap, json);
		logger.info("信用卡同步卡通道resultText={}", resultText);

		JSONObject object = null;
		try {
			object = JSONObject.parseObject(resultText);
		} catch (Exception e) {
			logger.error("getCardListFromThird JSONObject parseObject error");
		}
		if (object == null) {
			return;
		}
		if (object.containsKey("status")) {
			String status = object.getString("status");
			if (CommonConstants.LEY_RESULT_SUCCESS.equals(status)) {
				JSONArray array = JSONArray.parseArray(object.getString("result"));
				for (int i = 0; i < array.size(); i++) {
					JSONObject objectResult = array.getJSONObject(i);
					String stationBankCardChannelId = objectResult.getString("stationBankCardChannelId");
					String bankCardId = objectResult.getString("bankCardId");
					String stationChannelId = objectResult.getString("stationChannelId");
					Integer sort = objectResult.getInteger("sort");
					String imgUrlPath = objectResult.getString("imgUrlPath");
					String name = objectResult.getString("name");
					String description = objectResult.getString("description");

					TCreditCard card = new TCreditCard();
					card.setBankId(bankId);
					card.setBankCardId(bankCardId);
					card.setStationChannelId(stationChannelId);
					card.setStationBankCardChannelId(stationBankCardChannelId);
					card.setSort(sort);
					card.setThirdStatus(1);
					card.setStatus(0);
					card.setImgUrlPath(imgUrlPath);
					card.setBankCardName(name);
					card.setDescription(description);

					TCreditCard tCreditCard = creditCardRepository.queryTCreditCardByStationBankCardChannelId(stationBankCardChannelId);
					if (tCreditCard != null) {
						card.setId(tCreditCard.getId());
						card.setUpdateTime(new Date());
						UpdateTool.copyProperties(tCreditCard, card);
					} else {
						card.setCreateTime(new Date());
					}

					creditCardRepository.save(card);
					if(i == 0 && page == 1) {
						TCreditBank tbank = creditProductRepository.queryTCreditBankByBankId(bankId);
						tbank.setFristBankCardUrl(imgUrlPath);
						creditProductRepository.saveAndFlush(tbank);
					}
					//getCardChannelById(stationBankCardChannelId);
					feignRedisServiceClient.zadd(bankId, 0, stationBankCardChannelId);
				}
				JSONObject paging = JSONArray.parseObject(object.getString("paging"));

				Integer total = paging.getInteger("total");
				Integer size = paging.getInteger("size");
				if (page > Math.ceil(total / Double.valueOf(size))) {
					Set set = feignRedisServiceClient.zrange(bankId, 0, 200);
					creditCardRepository.updateStationBankCardChannelId(bankId,  new ArrayList<>(set));
					feignRedisServiceClient.del(bankId);
					return;
				} else {
					getCardListFromThird(bankId, paging.getInteger("current") + 1);
				}
			} else {
				logger.error("getCardListFromThird return data execption resultText={}", resultText);
			}
		}
	}

	public void getCardChannelById(String id) {
		String url = baseHost + "/credit/open/apply/card/" + id; // {通道id}
		// 生成时间戳
		String timestamp = String.valueOf(System.currentTimeMillis());
		// 公钥加密
		String sign = RsaUtils.encrypt(publicKey, String.valueOf(timestamp));
		// 建立请求头部数据
		Map<String, String> baseMap = new HashMap<>();
		baseMap.put("X-Auth-OEM", oemID);
		baseMap.put("X-Open-Sign", sign);
		baseMap.put("X-Open-Merchant", merchant);
		baseMap.put("X-Open-Timestamp", timestamp);

		logger.info(
				"timestamp=" + timestamp + ",sign=" + sign + ",同步申卡银行通道详情解析结果=" + RsaUtils.decrypt(privateKey, sign));
		// 建立GET请求
		String resultText = HttpClient.doGet(url, baseMap);
		logger.info("信用卡同步卡通道详情resultText={}", resultText);
	}

	@Override
	@RequestMapping(method = RequestMethod.POST, value = "/m2.0/credit/getBankPageList")
	@ApiOperation(value = "获取银行列表接口")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "pageNum", value = "页码", dataType = "int", required = true, paramType = "query"),
			@ApiImplicitParam(name = "pageSize", value = "每页多少条", dataType = "int", required = true, paramType = "query"),
			@ApiImplicitParam(name = "bankName", value = "银行名称(模糊查询)", required = false, dataType = "string", paramType = "query"),
			@ApiImplicitParam(name = "status", value = "0:未上架 1：已上架", required = false, dataType = "int", paramType = "query") })
	public Page<TCreditBank> getBankPageList(@RequestParam(value = "pageNum", required = true) Integer pageNum,
			@RequestParam(value = "pageSize", required = true) Integer pageSize,
			@RequestParam(value = "bankName", required = false) String bankName,
			@RequestParam(value = "status", required = false) Integer status) {
		Specification<TCreditBank> specification = new Specification<TCreditBank>() {

			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<TCreditBank> root, CriteriaQuery<?> query,
					CriteriaBuilder criteriaBuilder) {
				List<Predicate> predicates = new ArrayList<Predicate>();
				if (StringUtils.isNoneBlank(bankName)) {
					predicates.add(criteriaBuilder.like(root.get("bankName"), "%" + bankName + "%"));
				}
				if (status != null) {
					predicates.add(criteriaBuilder.equal(root.get("status"), status));
				}
				Predicate[] pre = new Predicate[predicates.size()];
				query.orderBy(criteriaBuilder.asc(root.get("sort")));
				return query.where(predicates.toArray(pre)).getRestriction();
			}
		};
		Pageable pageable = new PageRequest(pageNum == 0 ? pageNum : pageNum - 1, pageSize);
		org.springframework.data.domain.Page<TCreditBank> page = creditProductRepository.findAll(specification, pageable);
		pageNum = (pageNum == 0 ? 1 : pageNum);
		Page<TCreditBank> localPage = new Page<>(page.getContent(), page.getTotalElements(), pageNum, page.getSize());
		List<TCreditBank> list = localPage.getContent();
		for (TCreditBank bank : list) {
			bank.setThirdStatusName(WechartStatusTypeEnum.getEnumByKey(bank.getThridStatus()).getValue());
			bank.setStatusName(ChannelStatusTypeEnum.getEnumByKey(bank.getStatus()).getValue());
		}
		return localPage;
	}

	@Override
	@ApiOperation(value = "查询银行详情接口")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "id", value = "银行标识", dataType = "int", required = true, paramType = "query") })
	@RequestMapping(method = RequestMethod.POST, value = "/m2.0/credit/selectBankById")
	public TCreditBank selectBankById(@RequestParam(value = "id", required = true) Integer id) {
		Optional<TCreditBank> bank = creditProductRepository.findById(id);
		TCreditBank bankInfo = bank.get();
		bankInfo.setThirdStatusName(WechartStatusTypeEnum.getEnumByKey(bankInfo.getThridStatus()).getValue());
		bankInfo.setStatusName(ChannelStatusTypeEnum.getEnumByKey(bankInfo.getStatus()).getValue());
		return bankInfo;
	}

	@Override
	@ApiOperation(value = "更新银行信息接口")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "userId", value = "操作用户标识", dataType = "int", required = true, paramType = "query"),
			@ApiImplicitParam(name = "id", value = "银行标识", dataType = "int", required = true, paramType = "query"),
			@ApiImplicitParam(name = "sort", value = "银行排序", dataType = "int", paramType = "query"),
			@ApiImplicitParam(name = "rebetDescription", value = "分润要求", dataType = "string", paramType = "query"),
			@ApiImplicitParam(name = "description", value = "详情描述介绍", dataType = "string", paramType = "query") })
	@RequestMapping(method = RequestMethod.POST, value = "/m2.0/credit/updateBankById")
	public int updateBankById(@RequestParam(value = "userId", required = true) Integer userId,
			@RequestParam(value = "id", required = true) Integer id,
			@RequestParam(value = "sort", required = true) Integer sort,
			@RequestParam(value = "rebetDescription", required = true) String rebetDescription,
			@RequestParam(value = "description", required = true) String description) {

		Optional<TCreditBank> bank = creditProductRepository.findById(id);
		TCreditBank bankInfo = bank.get();

		TCreditBank newBank = new TCreditBank();

		UpdateTool.copyProperties(bankInfo, newBank);

		newBank.setId(id);
		newBank.setSort(sort);
		newBank.setRebetDescription(rebetDescription);
		newBank.setDescription(description);
		newBank.setUpdateUser(String.valueOf(userId));

		creditProductRepository.saveAndFlush(newBank);
		return 1;
	}

	@Override
	@ApiOperation(value = "银行上下架操作")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "userId", value = "操作用户标识", dataType = "int", required = true, paramType = "query"),
			@ApiImplicitParam(name = "status", value = "上下架状态：0：下架 1：上架", dataType = "int", required = true, paramType = "query"),
			@ApiImplicitParam(name = "id", value = "通道标识", dataType = "int", required = true, paramType = "query") })
	@RequestMapping(method = RequestMethod.POST, value = "/m2.0/credit/updateStatusById")
	public int updateStatusById(@RequestParam(value = "userId", required = true) Integer userId,
			@RequestParam(value = "id", required = true) Integer id,
			@RequestParam(value = "status", required = true) Integer status) {
		Optional<TCreditBank> creditProduct = creditProductRepository.findById(id);
		TCreditBank bank = creditProduct.get();

		TCreditBank tbank = new TCreditBank();
		UpdateTool.copyProperties(bank, tbank);

		tbank.setStatus(status);
		tbank.setUpdateUser(String.valueOf(userId));
		creditProductRepository.saveAndFlush(tbank);
		return 1;
	}

	@Override
	@RequestMapping(method = RequestMethod.POST, value = "/m2.0/credit/getBankCardPageList")
	@ApiOperation(value = "获取银行卡列表接口")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "pageNum", value = "页码", dataType = "int", required = true, paramType = "query"),
			@ApiImplicitParam(name = "pageSize", value = "每页多少条", dataType = "int", required = true, paramType = "query"),
			@ApiImplicitParam(name = "bankCardName", value = "银行卡名称(模糊查询)", required = false, dataType = "string", paramType = "query"),
			@ApiImplicitParam(name = "status", value = "0:未上架 1：已上架", required = false, dataType = "int", paramType = "query"),
			@ApiImplicitParam(name = "bankId", value = "第三方银行标识", required = false, dataType = "string", paramType = "query") })
	public Page<TCreditCard> getBankCardPageList(@RequestParam(value = "pageNum", required = true) Integer pageNum,
			@RequestParam(value = "pageSize", required = true) Integer pageSize,
			@RequestParam(value = "bankCardName", required = false) String bankCardName,
			@RequestParam(value = "status", required = false) Integer status,
			@RequestParam(value = "bankId", required = false) String bankId) {

		Specification<TCreditCard> specification = new Specification<TCreditCard>() {

			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<TCreditCard> root, CriteriaQuery<?> query,
					CriteriaBuilder criteriaBuilder) {
				List<Predicate> predicates = new ArrayList<Predicate>();
				if (StringUtils.isNoneBlank(bankCardName)) {
					predicates.add(criteriaBuilder.like(root.get("bankCardName"), "%" + bankCardName + "%"));
				}
				if (status != null) {
					predicates.add(criteriaBuilder.equal(root.get("status"), status));
				}
				if (bankId != null) {
					predicates.add(criteriaBuilder.equal(root.get("bankId"), bankId));
				}
				Predicate[] pre = new Predicate[predicates.size()];
				query.orderBy(criteriaBuilder.asc(root.get("sort")));
				return query.where(predicates.toArray(pre)).getRestriction();
			}
		};
		Pageable pageable = new PageRequest(pageNum == 0 ? pageNum : pageNum - 1, pageSize);
		org.springframework.data.domain.Page<TCreditCard> page = creditCardRepository.findAll(specification, pageable);
		pageNum = (pageNum == 0 ? 1 : pageNum);
		Page<TCreditCard> localPage = new Page<>(page.getContent(), page.getTotalElements(), pageNum, page.getSize());
		List<TCreditCard> list = localPage.getContent();
		for (TCreditCard card : list) {
			card.setThirdStatusName(WechartStatusTypeEnum.getEnumByKey(card.getThirdStatus()).getValue());
			card.setStatusName(ChannelStatusTypeEnum.getEnumByKey(card.getStatus()).getValue());
		}
		return localPage;
	}

	@Override
	@ApiOperation(value = "查询银行卡详情接口")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "id", value = "银行卡标识", dataType = "int", required = true, paramType = "query") })
	@RequestMapping(method = RequestMethod.POST, value = "/m2.0/credit/selectBankCardById")
	public TCreditCard selectBankCardById(@RequestParam(value = "id", required = true) Integer id) {
		Optional<TCreditCard> card = creditCardRepository.findById(id);
		TCreditCard cardInfo = card.get();
		cardInfo.setThirdStatusName(WechartStatusTypeEnum.getEnumByKey(cardInfo.getThirdStatus()).getValue());
		cardInfo.setStatusName(ChannelStatusTypeEnum.getEnumByKey(cardInfo.getStatus()).getValue());
		return cardInfo;
	}

	@Override
	@ApiOperation(value = "更新银行卡接口")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "userId", value = "操作用户标识", dataType = "int", required = true, paramType = "query"),
			@ApiImplicitParam(name = "id", value = "银行标识", dataType = "int", required = true, paramType = "query"),
			@ApiImplicitParam(name = "sort", value = "银行排序", dataType = "int", paramType = "query"),
			@ApiImplicitParam(name = "description", value = "详情描述介绍", dataType = "string", paramType = "query") })
	@RequestMapping(method = RequestMethod.POST, value = "/m2.0/credit/updateBankCardById")
	public int updateBankCardById(@RequestParam(value = "userId", required = true) Integer userId,
			@RequestParam(value = "id", required = true) Integer id,
			@RequestParam(value = "sort", required = false) Integer sort,
			@RequestParam(value = "description", required = false) String description) {

		Optional<TCreditCard> card = creditCardRepository.findById(id);
		TCreditCard cardInfo = card.get();

		TCreditCard newCard = new TCreditCard();

		UpdateTool.copyProperties(cardInfo, newCard);

		newCard.setId(id);
		newCard.setSort(sort);
		newCard.setDescription(description);
		newCard.setUpdateUser(String.valueOf(userId));

		creditCardRepository.saveAndFlush(newCard);
		return 1;
	}

	@Override
	@ApiOperation(value = "银行卡上下架操作")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "userId", value = "操作用户标识", dataType = "int", required = true, paramType = "query"),
			@ApiImplicitParam(name = "status", value = "上下架状态：0：下架 1：上架", dataType = "int", required = true, paramType = "query"),
			@ApiImplicitParam(name = "id", value = "通道标识", dataType = "int", required = true, paramType = "query") })
	@RequestMapping(method = RequestMethod.POST, value = "/m2.0/credit/updateCardStatusById")
	public int updateCardStatusById(@RequestParam(value = "userId", required = true) Integer userId,
			@RequestParam(value = "id", required = true) Integer id,
			@RequestParam(value = "status", required = true) Integer status) {
		Optional<TCreditCard> creditCard = creditCardRepository.findById(id);
		TCreditCard card = creditCard.get();

		TCreditCard tcard = new TCreditCard();
		UpdateTool.copyProperties(card, tcard);

		tcard.setStatus(status);
		tcard.setUpdateUser(String.valueOf(userId));

		creditCardRepository.saveAndFlush(tcard);
		return 1;
	}

	private static final String redisValidateCode = "credit:marvel:validatecode";

	@Override
	@ApiOperation(value = "获取申卡验证码")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "userPhone", value = "手机号", required = true, dataType = "string", paramType = "query") })
	@RequestMapping(method = RequestMethod.POST, value = "/m2.0/credit/validateCode")
	public String validateCode(@RequestParam(value = "userPhone", required = true) String userPhone) {
		// 生成随机字串
		String verifyCode = VerifyCodeUtils.generateVerifyCode(4);
		feignRedisServiceClient.set(redisValidateCode + userPhone, verifyCode, 5 * 60);
		logger.info("credit validateCode userPhone={} verifyCode={}", userPhone, verifyCode);
		return verifyCode;
	}

	private static final String redisSmsCode = "credit:marvel:sms";

	@Override
	@ApiOperation(value = "获取申卡手机验证码")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "userPhone", value = "手机号", required = true, dataType = "string", paramType = "query"),
			@ApiImplicitParam(name = "validateCode", value = "图形验证码", required = true, dataType = "string", paramType = "query"),
			@ApiImplicitParam(name = "brandId", value = "贴牌标识", required = true, dataType = "long", paramType = "query") })
	@RequestMapping(method = RequestMethod.POST, value = "/m2.0/credit/smsCode")
	public Boolean smsCode(@RequestParam(value = "userPhone", required = true) String userPhone,
			@RequestParam(value = "validateCode", required = true) String validateCode,
			@RequestParam(value = "brandId", required = true) Long brandId) {
		String redisValateCode = (String) feignRedisServiceClient.get(redisValidateCode + userPhone);
		if (!validateCode.equals(redisValateCode)) {
			throw new RuntimeException("图形验证码错误");
		}
		String smsCode = VerifyCodeUtils.generateVerifyCode(6);
		feignRedisServiceClient.set(redisSmsCode + userPhone, smsCode, 5 * 60);
		feignNoticeSendClient.sendNotice(userPhone, new String[] { smsCode }, NoticeTpIIdEnum.TYPE_NOTICE_TPLID.getValue(), brandId);
		return true;
	}

	@Override
	@ApiOperation(value = "保存订单申卡订单")
	@ApiImplicitParams({
			@ApiImplicitParam(name = "userId", value = "用户表示", required = true, dataType = "int", paramType = "query"),
			@ApiImplicitParam(name = "userName", value = "用户名字", required = true, dataType = "string", paramType = "query"),
			@ApiImplicitParam(name = "userPhone", value = "用户手机号", required = true, dataType = "string", paramType = "query"),
			@ApiImplicitParam(name = "idCard", value = "用户身份证号", required = true, dataType = "string", paramType = "query"),
			@ApiImplicitParam(name = "bankCardChannelId", value = "卡种通道标识", required = true, dataType = "string", paramType = "query"),
			@ApiImplicitParam(name = "smsCode", value = "短信验证码", required = true, dataType = "string", paramType = "query"),
			@ApiImplicitParam(name="source",value="订单来源", required = true, dataType="string", paramType = "query")})
	public String saveCreditOrder(
			@RequestParam(value = "userId", required = true) Integer userId,
			@RequestParam(value = "userName", required = true) String userName,
			@RequestParam(value = "userPhone", required = true) String userPhone,
			@RequestParam(value = "idCard", required = true) String idCard,
			@RequestParam(value = "bankCardChannelId", required = true) String bankCardChannelId,
			@RequestParam(value = "smsCode", required = true) String smsCode,
			@RequestParam(value = "source", required=true) String source) {

		*/
/**
		 * 验证码识别
		 *//*

		String frontSms = feignRedisServiceClient.get(redisSmsCode + userPhone);
		if (frontSms == null || !frontSms.equals(smsCode)) {
			 throw new RuntimeException("手机验证码错误");
		}

		if(!VerifyUtil.cardCodeVerifySimple(idCard)) {
			throw new RuntimeException("身份证号格式错误");
		}

		if(!VerifyUtil.isPhone(userPhone)) {
			throw new RuntimeException("手机号格式错误");
		}

		TCreditCard card = creditCardRepository.queryTCreditCardByStationBankCardChannelId(bankCardChannelId);
		TCreditBank bank = creditProductRepository.queryTCreditBankByBankId(card.getBankId());

		TCreditOrder order = new TCreditOrder();
		order.setMarketId(bank.getMarketId());

		TUser tuser = feignUserServiceClient.getUserID(userId);
		if (tuser == null) {
			throw new RuntimeException("用户不存在");
		}
		order.setSource(source);
		order.setBrandId(tuser.getBrandId());
		order.setUserId(userId);
		order.setUserName(userName);
		order.setUserPhone(userPhone);
		order.setIdCard(idCard);

		String clientNumber = OrderNoUtil.getBuyOrderNo("C");
		order.setClientNo(clientNumber);
		order.setCallbackUrl(callbackCreditUrl);
		order.setStationChannelId(bank.getBankId());
		order.setBankCardChannelId(bankCardChannelId);
		order.setProfiltType(bank.getProfitType());
		order.setProfitPerMoney(bank.getProfitPerMoney());
		order.setBankCardName(card.getBankCardName());

		order.setStatus(LoanOrderStatusTypeEnum.TYPE_STAUTS_INIT.getKey());
		order.setCreateTime(new Date());

		creditOrderRepository.saveAndFlush(order);

		String result = cardSaveToThrid(order);

		if(result != null && (result.startsWith("http") || result.startsWith("HTTP"))) {
			feignRedisServiceClient.del(redisSmsCode + userPhone);
		}

		return result;
	}

	public String cardSaveToThrid(TCreditOrder order) {
		String url = baseHost + "/credit/open/apply/card/save";
		// 生成时间戳
		String timestamp = String.valueOf(System.currentTimeMillis());
		// 公钥加密
		String sign = RsaUtils.encrypt(publicKey, String.valueOf(timestamp));
		// 建立请求头部数据
		Map<String, String> baseMap = new HashMap<>();
		baseMap.put("X-Auth-OEM", oemID);
		baseMap.put("X-Open-Sign", sign);
		baseMap.put("X-Open-Merchant", merchant);
		baseMap.put("X-Open-Timestamp", timestamp);
		// 建立请求参数
		Map<String, Object> map = new HashMap<>();
		// 申请人手机号
		map.put("mobile", order.getUserPhone());
		// 申请人姓名
		map.put("name", order.getUserName());
		// 申请人身份证号
		map.put("idCard", order.getIdCard());
		// 通道id 网申列表中的的stationChannelId
		map.put("stationChannelId", order.getStationChannelId());
		// 回调地址
		map.put("callbackUrl", order.getCallbackUrl());
		// 客户端编号，唯一请求标识
		map.put("clientNo", order.getClientNo());

		map.put("stationBankCardChannelId", order.getBankCardChannelId());

		// 建立post请求，传递json格式参数
		String resultText = HttpClient.doPost(url, baseMap, JSON.toJSONString(map));
		logger.info("submit 申卡 order return resultText={}", resultText);

		JSONObject object = null;
		try {
			object = JSONObject.parseObject(resultText);
		} catch (Exception e) {
			logger.error("cardSaveToThrid JSONObject parseObject error");
		}
		String message = null;
		if (object == null) {
			return "服务异常";
		}

		if (object.containsKey("status")) {
			String status = object.getString("status");
			TCreditOrder tOrder = creditOrderRepository.queryTLoanOrderByClientNumber(order.getClientNo());
			if (CommonConstants.LEY_RESULT_SUCCESS.equals(status)) {
				JSONObject objectR = JSONObject.parseObject(object.getString("result"));
				String tradeNo = objectR.getString("tradeNo");
				String creditUrl = objectR.getString("url");

				tOrder.setUrl(creditUrl);
				tOrder.setTradeNo(tradeNo);
				tOrder.setSubmitTime(new Date());
				tOrder.setStatus(LoanOrderStatusTypeEnum.TYPE_STATUS_SUBMIT.getKey());

				message = creditUrl;
			} else {
				tOrder.setUrl(null);
				tOrder.setTradeNo(null);
				tOrder.setSubmitTime(new Date());
				tOrder.setStatus(LoanOrderStatusTypeEnum.TYPE_STAUTS_FAILURE.getKey());
				message = object.getString("message");
				tOrder.setFailureMassage(message);
			}
			creditOrderRepository.saveAndFlush(tOrder);
		}
		return message;
	}

	//查找总代理
	private TUserAgential findAgentialKing(Long userId){
		TUser user = feignUserServiceClient.queryUser(userId);
		if (user == null){
			logger.info("用户{}不存在，未查询到总代理商！",userId);
			return null;
		}
		TUserAgential userAgential = feignUserServiceClient.findAgentialKingBySysUserId(userId);
		if(userAgential == null) {
			if (user.getPreUserId()==null){
				logger.info("用户{}没有父级，查询总代理商结束！",userId);
				return null;
			}
			TUser nextUser = feignUserServiceClient.queryUser(user.getPreUserId());
			if(nextUser == null  || nextUser.getPreUserId() == null) {
				logger.info("用户{}不存在，未查询到总代理商！",user.getPreUserId());
				return null;
			}
			return findAgentialKing(nextUser.getId());
		}
		return userAgential;
	}


	@Override
	@ApiOperation(value = "申卡回调接口")
	@ApiImplicitParams({
		  @ApiImplicitParam(name="jsonText",value="接收的回调字符串", required = true, dataType="string", paramType = "query")})
	@RequestMapping(method = RequestMethod.POST, value = "/m2.0/credit/creditCallBack")
	public boolean creditCallBack(@RequestParam(value = "jsonText", required = true) String jsonText) {
		logger.info("====================申请信用卡回调开始===================jsonText={}", jsonText);

		JSONObject object = JSONObject.parseObject(jsonText);
		String callbackType = object.getString("callbackType");
		if(!"CALLBACK_SUCCESS".equals(callbackType)) {
			//回调类型不成功
			logger.info("====================申请信用卡回调失败===================jsonText={}", jsonText);
			return false;
		}
		//验签
		String timestampColum = object.getString("timestamp");
		String signT = object.getString("sign");//第三方sign
		String timestamp = RsaUtils.decrypt(privateKey, signT);
		if(timestampColum.equals(timestamp)) {
			String clientNo = object.getString("clientNo");
//			String transNo = object.getString("transNo");
			String userPrice = object.getString("userPrice");

			TCreditOrder order = creditOrderRepository.queryTLoanOrderByClientNumber(clientNo);
			if(order.getStatus() == LoanOrderStatusTypeEnum.TYPE_STATUS_FINISH.getKey() || order.getStatus() == LoanOrderStatusTypeEnum.TYPE_STATUS_FENRUN.getKey()) {
				logger.info("====================申请信用卡回调订单已经修改===================clentNo={}", order.getClientNo());
				return true;
			}
			BigDecimal userPerfitMoney = new BigDecimal(userPrice).divide(new BigDecimal("100"), 2, RoundingMode.FLOOR);
			order.setUserPrice(userPerfitMoney);
			order.setCallback_time(new Date());
			order.setStatus(LoanOrderStatusTypeEnum.TYPE_STATUS_FINISH.getKey());
			creditOrderRepository.saveAndFlush(order);

			TUser tuser = feignUserServiceClient.getUserID(order.getUserId());
			//进行分润操作
			ProfitThreeForm threeForm = new ProfitThreeForm();

			threeForm.setOrderCode(clientNo);
			threeForm.setUserId(Long.valueOf(order.getUserId()));

            */
/*//*
/给总代分润
			BigDecimal percent=new BigDecimal(profitPercent).divide(new BigDecimal("2"),2,BigDecimal.ROUND_HALF_DOWN);
			TUserAgential agentialKing=findAgentialKing(order.getUserId().longValue());
			if (agentialKing!=null){
				feignAgentialAccountServiceClient.agentialBalanceAddOrSub(agentialKing.getUserId(),agentialKing.getBrandId(),"0",null,null,userPerfitMoney.multiply(percent).setScale(2,BigDecimal.ROUND_HALF_DOWN), AgentialBalanceHistoryTypeEnum.CREDIT.getKey(),clientNo,order.getUserId().longValue());
				logger.info("=======================给userId为{} 总代 分润 {}==========================",agentialKing.getUserId(),userPerfitMoney.multiply(percent).setScale(2,BigDecimal.ROUND_HALF_DOWN));
				threeForm.setAmount(userPerfitMoney.subtract(userPerfitMoney.multiply(percent)).setScale(2, BigDecimal.ROUND_HALF_DOWN));
			}
			else {
				threeForm.setAmount(userPerfitMoney.subtract(userPerfitMoney.multiply(new BigDecimal(profitPercent))).setScale(2, BigDecimal.ROUND_HALF_DOWN));
			}*//*

			threeForm.setAmount(userPerfitMoney.subtract(userPerfitMoney.multiply(new BigDecimal(profitPercent))).setScale(2, BigDecimal.ROUND_HALF_DOWN));
			threeForm.setChannelId(9999);//手动加入id=9999
			threeForm.setBrandId(Integer.valueOf(order.getBrandId().toString()));
			threeForm.setProfitTypeId(1);
			threeForm.setCityId(tuser.getCityId());
//			threeForm.setProfitLevel(0);
			Boolean reusltFit = feignProfitTaskServiceClient.processProfitThreeForm(threeForm);
			logger.info("====================申请信用卡回调订单分润开始===================clentNo={}", order.getClientNo());
			if(reusltFit) {
				TCreditOrder orderFit = creditOrderRepository.queryTLoanOrderByClientNumber(clientNo);
				orderFit.setStatus(LoanOrderStatusTypeEnum.TYPE_STATUS_FENRUN.getKey());
				orderFit.setRebet_time(new Date());
				creditOrderRepository.saveAndFlush(orderFit);
				logger.info("====================申请信用卡回调订单分润成功===================clentNo={}", order.getClientNo());
			} else {
				logger.info("====================申请信用卡回调订单分润未全部完成===================clentNo={}", order.getClientNo());
			}
		} else {
			//验签失败
			logger.info("====================申请信用卡回调订单验签失败===================jsonText={}", jsonText);
			return false;
		}
		logger.info("====================申请信用卡回调结束===================jsonText={}", jsonText);
		return true;
	}

	@Override
	@ApiImplicitParams({
		@ApiImplicitParam(name = "pageNum", value = "页码", required = true, dataType = "int", paramType = "query"),
		@ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, dataType = "string", paramType = "query"),
		@ApiImplicitParam(name = "clientNo", value = "订单号", required = false, dataType = "string", paramType = "query"),
		@ApiImplicitParam(name = "userPhone", value = "用户手机号", required = false, dataType = "string", paramType = "query"),
		@ApiImplicitParam(name = "userId", value = "用户标识", required = false, dataType = "int", paramType = "query"),
		@ApiImplicitParam(name = "brandId", value = "贴牌标识", required = false, dataType = "long", paramType = "query"),
		@ApiImplicitParam(name = "status", value = "订单状态", required = false, dataType = "int", paramType = "query"),
		@ApiImplicitParam(name="agentUserId",value="代理商用户标示", required = false, dataType="int", paramType = "query")})
	public Page<TCreditOrder> getCreditOrderPageList(@RequestParam(value = "pageNum", required = true) Integer pageNum,
			@RequestParam(value = "pageSize", required = true) Integer pageSize,
			@RequestParam(value = "clientNo", required = false) String clientNo,
			@RequestParam(value = "userPhone", required = false) String userPhone,
			@RequestParam(value = "userId", required = false) Integer userId,
			@RequestParam(value = "brandId", required = false) Long brandId,
			@RequestParam(value = "status", required = false) Integer status,
			@RequestParam(value = "agentUserId", required = false) Integer agentUserId) {
		List<Integer> subUserIdList = null;
		if(agentUserId != null) {
			subUserIdList = feignUserRelationServiceClient.querySubordinateUserIds(agentUserId);
		}
		List<Integer> finalSubUserIdList = subUserIdList;
		if(agentUserId != null && (finalSubUserIdList == null || finalSubUserIdList.size() == 0)) {
			return new Page<TCreditOrder>();
		}
		Specification<TCreditOrder> specification = new Specification<TCreditOrder>() {

			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<TCreditOrder> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder) {
				List<Predicate> predicates = new ArrayList<Predicate>();
				if (StringUtils.isNoneBlank(clientNo)) {
					predicates.add(criteriaBuilder.equal(root.get("clientNo"), clientNo));
				}
				if (StringUtils.isNoneBlank(userPhone)) {
					predicates.add(criteriaBuilder.equal(root.get("userPhone"), userPhone));
				}
				if (userId != null) {
					predicates.add(criteriaBuilder.equal(root.get("userId"), userId));
				}
				if (brandId != null) {
					predicates.add(criteriaBuilder.equal(root.get("brandId"), brandId));
				}
				if (status != null) {
					predicates.add(criteriaBuilder.equal(root.get("status"), status));
				}
				if(finalSubUserIdList != null && finalSubUserIdList.size() > 0) {
					Path<Object> path = root.get("userId");
					CriteriaBuilder.In<Object> in = criteriaBuilder.in(path);
					for(Integer id : finalSubUserIdList) {
						in.value(id);
					}
					predicates.add(criteriaBuilder.and(in));
				}
				Predicate[] pre = new Predicate[predicates.size()];
				query.orderBy(criteriaBuilder.desc(root.get("id")));
				return query.where(predicates.toArray(pre)).getRestriction();
			}
		};
		Pageable pageable = new PageRequest(pageNum == 0 ? pageNum : pageNum - 1, pageSize);
		org.springframework.data.domain.Page<TCreditOrder> page = creditOrderRepository.findAll(specification, pageable);
		pageNum = (pageNum == 0 ? 1 : pageNum);
		Page<TCreditOrder> localPage = new Page<>(page.getContent(), page.getTotalElements(), pageNum, page.getSize());
		List<TCreditOrder> list = localPage.getContent();
		for (TCreditOrder card : list) {
			card.setUserPhone(card.getUserPhone().replace(card.getUserPhone().substring(3, card.getUserPhone().length() - 4), "****"));
			card.setIdCard(card.getIdCard().replace(card.getIdCard().substring(1, card.getIdCard().length() - 1), "****************"));
			card.setStatusName(LoanOrderStatusTypeEnum.getEnumByKey(card.getStatus()).getValue());
		}
		return localPage;
	}

	@Override
	@ApiOperation(value = "获取申卡图片验证码")
	@ApiImplicitParams({
		  @ApiImplicitParam(name="userPhone",value="手机号", required = true, dataType="string", paramType = "query")})
	@RequestMapping(method = RequestMethod.POST, value = "/m2.0/credit/validateCodeStr")
	public String validateCodeStr(String userPhone) {
		String verifyCode = VerifyCodeUtils.generateVerifyCode(4);
		feignRedisServiceClient.set(redisValidateCode + userPhone, verifyCode, 5 * 60);
		logger.info("loan validateCode userPhone={} verifyCode={}", userPhone, verifyCode);

		int width = 100;// 宽
		int height = 40;// 高
		String fileName = verifyCode + ".jpg";
		String path = this.getClass().getResource("/").getPath() + "/" + fileName;
		File file = new File(path);

		String url = "";
		try {
			VerifyCodeUtils.outputImage(width, height, file, verifyCode);

			url = uploadService.uploadFile(file);
//			byte[] bytes = FileUtils.File2byte(file);
//			String byteStr = Base64.getEncoder().encodeToString(bytes);
//
//			url = feignFastdfsServiceClient.uploadFileStr(byteStr, fileName);
		} catch (IOException e) {
			logger.error("validateCodeStr error", e);
		} finally {
			file.delete();
		}
		return FASTDFS_BASE_URL + url;
	}


	@Override
	@RequestMapping(method = RequestMethod.POST,value = "/m2.0/credit/queryGroupByPhoneAndOrderByCount")
	public List<LeaderBoardJpaDTO> queryGroupByPhoneAndOrderByCount(@RequestParam(value = "brandId", required=true) Long brandId){
		Pageable pageable = PageRequest.of(0,6);
		org.springframework.data.domain.Page<LeaderBoardJpaDTO> leaderBoardJpaDTOS =
				creditOrderRepository.queryGroupByPhoneAndOrderByCount(pageable, brandId);
		List<LeaderBoardJpaDTO> content = leaderBoardJpaDTOS.getContent();
		return content;
	}



}
*/
